package com.bzkj.common.utils.poi;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.text.csv.CsvWriteConfig;
import cn.hutool.core.text.csv.CsvWriter;
import cn.hutool.core.util.URLUtil;
import com.bzkj.common.annotation.Excel;

import javax.servlet.http.HttpServletResponse;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * CSV导出工具类（支持@Excel注解解析）
 */
public class CsvExportUtils {

    private static final CsvWriteConfig DEFAULT_CONFIG = CsvWriteConfig.defaultConfig();

    /**
     * 导出到文件（自动解析@Excel注解）
     *
     * @param filePath 文件路径
     * @param dataList 数据列表
     * @param <T>      泛型类型
     * @throws IOException
     */
    public static <T> void exportToFile(String filePath, List<T> dataList) throws IOException {
        exportToFile(filePath, dataList, DEFAULT_CONFIG);
    }

    /**
     * 导出到文件（自定义配置）
     *
     * @param filePath 文件路径
     * @param dataList 数据列表
     * @param config   CSV配置
     * @param <T>      泛型类型
     * @throws IOException
     */
    public static <T> void exportToFile(String filePath, List<T> dataList,
                                        CsvWriteConfig config) throws IOException {
        if (dataList == null || dataList.isEmpty()) {
            return;
        }

        try (CsvWriter writer = createWriter(filePath, config)) {
            writeDataWithExcelAnnotation(writer, dataList);
        }
    }

    /**
     * Web导出（自动解析@Excel注解）
     *
     * @param response HttpServletResponse
     * @param fileName 文件名
     * @param dataList 数据列表
     * @param <T>      泛型类型
     * @throws IOException
     */
    public static <T> void exportToWeb(HttpServletResponse response, String fileName,
                                       List<T> dataList) throws IOException {
        exportToWeb(response, fileName, dataList, DEFAULT_CONFIG);
    }

    /**
     * Web导出（自定义配置）
     *
     * @param response HttpServletResponse
     * @param fileName 文件名
     * @param dataList 数据列表
     * @param config   CSV配置
     * @param <T>      泛型类型
     * @throws IOException
     */
    public static <T> void exportToWeb(HttpServletResponse response, String fileName,
                                       List<T> dataList, CsvWriteConfig config) throws IOException {
        if (dataList == null || dataList.isEmpty()) {
            return;
        }

        response.setContentType("text/csv");
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
        response.setHeader("Content-Disposition",
                "attachment;filename=" + URLUtil.encode(fileName));

        try (OutputStream out = response.getOutputStream();
             CsvWriter writer = CsvUtil.getWriter(
                     new OutputStreamWriter(out, StandardCharsets.UTF_8), config)) {

            // 写入UTF-8 BOM头
            out.write(0xEF);
            out.write(0xBB);
            out.write(0xBF);

            writeDataWithExcelAnnotation(writer, dataList);
        }
    }

    /**
     * 创建CSV写入器
     */
    private static CsvWriter createWriter(String filePath, CsvWriteConfig config) throws IOException {
        return CsvUtil.getWriter(
                new OutputStreamWriter(new FileOutputStream(filePath), StandardCharsets.UTF_8),
                config
        );
    }

    /**
     * 解析@Excel注解并写入数据
     */
    private static <T> void writeDataWithExcelAnnotation(CsvWriter writer, List<T> dataList) {
        Class<?> clazz = dataList.get(0).getClass();

        // 1. 获取带@Excel注解的字段信息（保持顺序）
        LinkedHashMap<String, Excel> fieldAnnotations = new LinkedHashMap<>();
        for (Field field : clazz.getDeclaredFields()) {
            Excel excelAnnotation = field.getAnnotation(Excel.class);
            if (excelAnnotation != null) {
                fieldAnnotations.put(field.getName(), excelAnnotation);
            }
        }

        // 2. 生成表头
        String[] headers = fieldAnnotations.values().stream()
                .map(Excel::name)
                .toArray(String[]::new);
        writer.write(headers);

        // 3. 写入数据行
        for (T data : dataList) {
            Map<String, Object> fieldMap = BeanUtil.beanToMap(data);
            String[] row = new String[headers.length];
            int i = 0;

            for (Map.Entry<String, Excel> entry : fieldAnnotations.entrySet()) {
                String fieldName = entry.getKey();
                Excel excelAnnotation = entry.getValue();
                Object value = fieldMap.get(fieldName);
                row[i++] = convertValueByAnnotation(value, excelAnnotation);
            }

            writer.write(row);
        }
    }

    /**
     * 根据@Excel注解转换值
     */
    private static String convertValueByAnnotation(Object value, Excel excelAnnotation) {
        if (value == null) {
            return "";
        }

        // 处理readConverterExp转换（如：1=停用,2=启用）
        if (excelAnnotation.readConverterExp().length() > 0) {
            String[] conversions = excelAnnotation.readConverterExp().split(",");
            for (String conversion : conversions) {
                String[] parts = conversion.split("=");
                if (parts.length == 2 && value.toString().equals(parts[0].trim())) {
                    return parts[1].trim();
                }
            }
        }

        return value.toString();
    }
}